Untitled21.ipynb
No Headings
The table of contents shows headings in notebooks and supported files.
- File
- Edit
- View
- Run
- Kernel
- Settings
- Help
Kernel status: Idle
[10]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Step 0: Load the data
df = pd.read_csv(r"C:\Users\pappu\Downloads\DMP-01-Inclass-Exercises-File\DMP-01 Inclass Exercises File\Batch 66\DMP_01_data_TATAMOTORS.NS.csv", index_col=0, parse_dates=True)
df3 = df.copy()
# Step 1: Compute SMA50 and SMA200
df3['sma50'] = df3['Adj Close'].rolling(window=50).mean().shift(1)
df3['sma200'] = df3['Adj Close'].rolling(window=200).mean().shift(1)
# Step 2: Previous day's SMAs
df3['sma50_prev_day'] = df3['sma50'].shift(1)
df3['sma200_prev_day'] = df3['sma200'].shift(1)
# Step 3: Generate crossover signals
df3['signal'] = np.where(
(df3['sma50'] > df3['sma200']) & (df3['sma50_prev_day'] < df3['sma200_prev_day']), 1, 0
)
df3['signal'] = np.where(
(df3['sma50'] < df3['sma200']) & (df3['sma50_prev_day'] > df3['sma200_prev_day']), -1, df3['signal']
)
# Step 4: Buy and Sell prices
df3['buy_price'] = df3.apply(lambda x: x['Adj Close'] if x['signal'] == 1 else 0, axis=1)
df3['sell_price'] = df3.apply(lambda x: -x['Adj Close'] if x['signal'] == -1 else 0, axis=1)
# Step 5: Create trade_price and position
df3['trade_price'] = df3['buy_price'] + df3['sell_price']
df3['trade_price'] = df3['trade_price'].replace(0, np.nan).ffill()
df3['position'] = df3['signal'].replace(0, np.nan).ffill()
df3['position'] = df3['position'].fillna(0)
# Step 6: Strategy returns
df3['cc_returns'] = df3['Adj Close'].pct_change()
df3['strategy_returns'] = df3['cc_returns'] * df3['position']
# Step 7: Cumulative returns
df3[['cc_returns', 'strategy_returns']] = df3[['cc_returns', 'strategy_returns']].fillna(0)
df3[['cc_returns', 'strategy_returns']] = 1 + df3[['cc_returns', 'strategy_returns']]
df3[['cc_returns', 'strategy_returns']] = df3[['cc_returns', 'strategy_returns']].cumprod()
# Step 8: Drawdown calculation
df3['strategy_cummax'] = df3['strategy_returns'].cummax()
df3['drawdown'] = df3['strategy_returns'] / df3['strategy_cummax'] - 1
# Step 9: Plot cumulative returns and drawdown
plt.figure(figsize=(14, 6))
# Plot Cumulative Returns
plt.subplot(2, 1, 1)
plt.plot(df3['cc_returns'], label='Buy & Hold', linewidth=1.5)
plt.plot(df3['strategy_returns'], label='Strategy', linewidth=1.5)
plt.title('Cumulative Returns')
plt.legend()
plt.grid(True)
# Plot Drawdown
plt.subplot(2, 1, 2)
plt.plot(df3['drawdown'], color='red', label='Drawdown')
plt.title('Strategy Drawdown')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# Step 10: Print final results
print("📈 Buy & Hold Return:", round(df3['cc_returns'].iloc[-1], 2))
print("📊 Strategy Return:", round(df3['strategy_returns'].iloc[-1], 2))
print("📉 Max Drawdown:", round(df3['drawdown'].min() * 100, 2), "%")
📈 Buy & Hold Return: 1.53 📊 Strategy Return: 1.28 📉 Max Drawdown: -93.38 %
[4]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Load data
df = pd.read_csv(r"C:\Users\pappu\Downloads\DMP-01-Inclass-Exercises-File\DMP-01 Inclass Exercises File\Batch 66\DMP_01_data_TATAMOTORS.NS.csv", index_col=0, parse_dates=True)
df = df[['Adj Close']].copy()
# EMA calculations
df['EMA_20'] = df['Adj Close'].ewm(span=20, adjust=False).mean().shift(1)
df['EMA_50'] = df['Adj Close'].ewm(span=50, adjust=False).mean().shift(1)
df['EMA_20_prev'] = df['EMA_20'].shift(1)
df['EMA_50_prev'] = df['EMA_50'].shift(1)
# Signal generation
df['signal'] = np.where((df['EMA_20'] > df['EMA_50']) & (df['EMA_20_prev'] <= df['EMA_50_prev']), 1, 0)
df['signal'] = np.where((df['EMA_20'] < df['EMA_50']) & (df['EMA_20_prev'] >= df['EMA_50_prev']), -1, df['signal'])
# Trade prices
df['buy_price'] = df.apply(lambda x: x['Adj Close'] if x['signal'] == 1 else 0, axis=1)
df['sell_price'] = df.apply(lambda x: -x['Adj Close'] if x['signal'] == -1 else 0, axis=1)
df['trade_price'] = df['buy_price'] + df['sell_price']
df['trade_price'] = df['trade_price'].mask(df['trade_price'] == 0).ffill()
# Position tracking
df['position'] = df['signal'].mask(df['signal'] == 0).ffill()
# Strategy performance
df['cc_returns'] = df['Adj Close'].pct_change()
df['strategy_returns'] = df['cc_returns'] * df['position']
df[['cc_returns', 'strategy_returns']] = df[['cc_returns', 'strategy_returns']].fillna(0)
df[['cc_returns', 'strategy_returns']] = 1 + df[['cc_returns', 'strategy_returns']]
df[['cc_returns', 'strategy_returns']] = df[['cc_returns', 'strategy_returns']].cumprod()
# Drawdown calculation
df['strategy_cummax'] = df['strategy_returns'].cummax()
df['drawdown'] = df['strategy_returns'] / df['strategy_cummax'] - 1
# Plot
plt.figure(figsize=(14, 6))
plt.subplot(2, 1, 1)
plt.plot(df['cc_returns'], label='Buy & Hold', linewidth=1.5)
plt.plot(df['strategy_returns'], label='EMA 20/50 Strategy', linewidth=1.5)
plt.legend()
plt.title('Cumulative Returns')
plt.subplot(2, 1, 2)
plt.plot(df['drawdown'], color='red', label='Drawdown')
plt.title('Strategy Drawdown')
plt.grid(True)
plt.tight_layout()
plt.show()
Final Buy & Hold Return: 1.53 Final EMA 20/50 Strategy Return: 7.27 Max Drawdown: -0.55
Buy & Hold Final Return: 1.53 EMA 20 / SMA 50 Strategy Final Return: 6.78 Max Drawdown: -0.64
📊 Performance Summary:
Final Return Max Drawdown
Buy & Hold 1.53 -0.89
MACD Only 13029.19 -0.23
MACD + EMA50 1310.80 -0.36
MACD + RSI 1402.19 -0.36
📈 MACD-Only Strategy Trade Log:
Buy Date Buy Price Sell Date Sell Price P/L (%)
0 2015-06-22 437.603180 2015-06-02 463.879272 6.004548
1 2015-06-23 433.132782 2015-06-03 453.845642 4.782104
2 2015-06-24 427.768280 2015-06-04 448.232819 4.784024
3 2015-06-25 429.556427 2015-06-05 439.192657 2.243298
4 2015-06-26 434.722260 2015-06-08 432.735382 -0.457045
5 2015-06-29 425.433746 2015-06-09 437.156128 2.755395
6 2015-06-30 431.294952 2015-06-10 443.663055 2.867667
7 2015-07-01 441.576874 2015-06-11 427.370911 -3.217099
8 2015-07-02 433.530151 2015-06-12 419.026123 -3.345564
9 2015-07-03 430.301514 2015-06-15 423.546234 -1.569894
Adj Close EMA_12 EMA_26 MACD Signal_Line \
Date
2025-05-14 698.950012 682.658708 668.312165 14.346544 7.121504
2025-05-15 728.099976 689.649673 672.740891 16.908781 9.078959
2025-05-16 730.700012 695.965109 677.034160 18.930950 11.049357
2025-05-19 729.500000 701.124323 680.920518 20.203805 12.880247
2025-05-20 718.900024 703.859047 683.733815 20.125232 14.329244
2025-05-21 726.799988 707.388422 686.923902 20.464520 15.556299
2025-05-22 717.450012 708.936359 689.185095 19.751264 16.395292
2025-05-23 718.250000 710.369227 691.338051 19.031176 16.922469
2025-05-26 729.000000 713.235500 694.127825 19.107675 17.359510
2025-05-27 716.450012 713.730040 695.781320 17.948720 17.477352
signal position returns strategy_returns cumulative_returns \
Date
2025-05-14 1 1.0 -0.012364 -0.012364 12710.939907
2025-05-15 1 1.0 0.041705 0.041705 13241.054259
2025-05-16 1 1.0 0.003571 0.003571 13288.337911
2025-05-19 1 1.0 -0.001642 -0.001642 13266.514772
2025-05-20 1 1.0 -0.014530 -0.014530 13073.746119
2025-05-21 1 1.0 0.010989 0.010989 13217.412988
2025-05-22 1 1.0 -0.012865 -0.012865 13047.376539
2025-05-23 1 1.0 0.001115 0.001115 13061.924928
2025-05-26 1 1.0 0.014967 0.014967 13257.421891
2025-05-27 1 1.0 -0.017215 -0.017215 13029.190775
cum_max drawdown trade_return
Date
2025-05-14 13108.298404 -0.030314 NaN
2025-05-15 13241.054259 0.000000 NaN
2025-05-16 13288.337911 0.000000 NaN
2025-05-19 13288.337911 -0.001642 NaN
2025-05-20 13288.337911 -0.016149 NaN
2025-05-21 13288.337911 -0.005337 NaN
2025-05-22 13288.337911 -0.018133 NaN
2025-05-23 13288.337911 -0.017038 NaN
2025-05-26 13288.337911 -0.002327 NaN
2025-05-27 13288.337911 -0.019502 NaN
CAGR: 1.5806
Sharpe Ratio: 2.55
Sortino Ratio: 4.48
Max Drawdown: -0.2342
Average Trade Return (with SL/TP): -0.0219
Total Trades (with SL/TP): 94
[5]:
{'Final Return': 1412.52, 'Max Drawdown': -0.27, 'Sharpe Ratio': 1.99}[11]:
({'ADF Statistic': -48.51455618591484,
'p-value': 0.0,
'Critical Values': {'1%': -3.433005627914427,
'5%': -2.862713234984453,
'10%': -2.567394559656695},
'Stationary': True},
1.8530966156084383,
2.9185557791971077,
0.9564127760055186,
-0.3613217019225661,
<class 'statsmodels.iolib.summary.Summary'>
"""
OLS Regression Results
==============================================================================
Dep. Variable: returns R-squared: 0.008
Model: OLS Adj. R-squared: 0.007
Method: Least Squares F-statistic: 19.18
Date: Wed, 09 Jul 2025 Prob (F-statistic): 1.24e-05
Time: 20:41:07 Log-Likelihood: 5437.8
No. Observations: 2452 AIC: -1.087e+04
Df Residuals: 2450 BIC: -1.086e+04
Df Model: 1
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 0.0004 0.001 0.794 0.427 -0.001 0.001
MACD 0.0002 4.27e-05 4.380 0.000 0.000 0.000
==============================================================================
Omnibus: 443.390 Durbin-Watson: 1.968
Prob(Omnibus): 0.000 Jarque-Bera (JB): 5032.742
Skew: 0.504 Prob(JB): 0.00
Kurtosis: 9.946 Cond. No. 12.5
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
""")[ ]:
Common Tools
No metadata.
Advanced Tools
No metadata.
Anaconda Assistant
4.1.0
Agree to use Assistant
Anaconda Assistant is an AI-powered chat application designed to enhance the productivity of data scientists, developers, and researchers.
Terms and Conditions
By clicking the continue button, you agree to our Terms and Conditions and Privacy Policy.
Confirm Your Age
I hereby confirm that I'm older than 13 years old.
Data Collection (Optional)
Not enabled
Help us improve the Anaconda Assistant. Enabling data collection means you acknowledge and agree that we can collect messages and metadata, including sensitive information that may be in your conversations with Anaconda Assistant.
You can opt out of this at any time in the settings menu.
![Python [conda env:base] *](./macd_files/logo-64x64.png)